package com.xingxuecn.demos.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Map;

/**
 * 加密的切面
 * @author Kris at 2018/9/26 15:27
 */
@Component
@Aspect
@Order(1)//在注解方式中，用Order注解来设置切面执行顺序
public class EncryAspect {

    @Pointcut(value = "@annotation(com.xingxuecn.demos.annotation.NeedEncry)")
    private void expression(){}

    /**
     * 前置通知
     */
    @Before("@annotation(com.xingxuecn.demos.annotation.NeedEncry)")
    private void beFore(){
        System.out.println("加密切面：前置");
    }

    /**
     * 异常通知
     */
    @AfterThrowing("expression()")
    private void afterThrowing(){
        System.out.println("加密切面：你这个报错啦");
    }

    /**
     * 权限最大的切面。可以改变入参和返回值。
     * 一定注意，必须调用目标方法
     * 如做加密，解密，只能在Around里面做
     * @param point
     * @return
     */
    @Around("expression()")
    private Object around(ProceedingJoinPoint point){
        Object[] args = point.getArgs();
        System.out.println("加密切面：环绕通知取到入参"+ Arrays.toString(args));
        try {
            Object r = point.proceed();
            System.out.println("加密切面：环绕通知取到返回结果"+r);
            if(r!=null  &&  r instanceof Map){
                ((Map) r).put("code","200");
            }
            return r;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }


    /**
     * 后置通知
     */
    @After("expression()")
    private void after(){
        System.out.println("加密切面：后置");
    }

    /**
     * AfterReturning 可以拦截返回结果，但是不能改变返回结果
     * @param retVal
     */
    @AfterReturning(value="expression()",returning="retVal")
    private void afterReturning(Object retVal){
        System.out.println("加密切面：返回拦截"+retVal);
    }
}
